"""
扫码相机的驱动
"""

from ctypes import *
from enum import Enum
import gevent
import numpy as np

from dataclasses import dataclass

from settings import CODE_LIB_PATH
from tools.hd_logger import HdLogger


MV_CODEREADER_MAX_DEVICE_NUM = 256
INFO_MAX_BUFFER_SIZE = 64
MV_CODEREADER_GIGE_DEVICE = 0x00000001
MV_CODEREADER_ACCESS_Exclusive = 1

errorDict = {
    "0x0": "MV_CODEREADER_OK 成功，无错误",
    "0x00000000": "MV_CODEREADER_OK 成功，无错误",
    "0x80020000": "MV_CODEREADER_E_HANDLE 错误或无效的句柄",
    "0x80020001": "MV_CODEREADER_E_SUPPORT 不支持的功能",
    "0x80020002": "MV_CODEREADER_E_BUFOVER 缓存已满",
    "0x80020003": "MV_CODEREADER_E_CALLORDER 函数调用顺序错误",
    "0x80020004": "MV_CODEREADER_E_PARAMETER 错误的参数",
    "0x80020005": "MV_CODEREADER_E_RESOURCE 资源申请失败",
    "0x80020006": "MV_CODEREADER_E_NODATA 无数据",
    "0x80020007": "MV_CODEREADER_E_PRECONDITION 前置条件有误或运行环境已发生变化",
    "0x80020008": "MV_CODEREADER_E_VERSION 版本不匹配",
    "0x80020009": "MV_CODEREADER_E_NOENOUGH_BUF 传入的内存空间不足",
    "0x8002000A": "MV_CODEREADER_E_ABNORMAL_IMAGE 异常图像，可能是丢包导致图像不完整",
    "0x8002000B": "MV_CODEREADER_E_LOAD_LIBRARY 动态导入DLL失败",
    "0x8002000C": "MV_CODEREADER_E_NOOUTBUF 没有可输出的缓存",
    "0x8002000F": "MV_CODEREADER_E_FILE_PATH 文件路径错误",
    "0x800200FF": "MV_CODEREADER_E_UNKNOW 未知的错误",
    "0x80020100": "MV_CODEREADER_E_GC_GENERIC 通用错误",
    "0x80020101": "MV_CODEREADER_E_GC_ARGUMENT 参数非法",
    "0x80020102": "MV_CODEREADER_E_GC_RANGE 值超出范围",
    "0x80020103": "MV_CODEREADER_E_GC_PROPERTY 属性错误",
    "0x80020104": "MV_CODEREADER_E_GC_RUNTIME 运行环境有问题",
    "0x80020105": "MV_CODEREADER_E_GC_LOGICAL 逻辑错误",
    "0x80020106": "MV_CODEREADER_E_GC_ACCESS 节点访问条件有误",
    "0x80020107": "MV_CODEREADER_E_GC_TIMEOUT 超时",
    "0x80020108": "MV_CODEREADER_E_GC_DYNAMICCAST 转换异常",
    "0x800201FF": "MV_CODEREADER_E_GC_UNKNOW GenICam未知错误",
    "0x80020200": "MV_CODEREADER_E_NOT_IMPLEMENTED 命令不被设备支持",
    "0x80020201": "MV_CODEREADER_E_INVALID_ADDRESS 访问的目标地址不存在",
    "0x80020202": "MV_CODEREADER_E_WRITE_PROTECT 目标地址不可写",
    "0x80020203": "MV_CODEREADER_E_ACCESS_DENIED 设备无访问权限",
    "0x80020204": "MV_CODEREADER_E_BUSY 设备忙或网络断开",
    "0x80020205": "MV_CODEREADER_E_PACKET 网络包数据错误",
    "0x80020206": "MV_CODEREADER_E_NETER 网络相关错误",
    "0x80020221": "MV_CODEREADER_E_IP_CONFLICT 设备IP冲突",
    "0x80020300": "MV_CODEREADER_E_USB_READ 读USB出错",
    "0x80020301": "MV_CODEREADER_E_USB_WRITE 写USB出错",
    "0x80020302": "MV_CODEREADER_E_USB_DEVICE 设备异常",
    "0x80020303": "MV_CODEREADER_E_USB_GENICAM GenICam相关错误",
    "0x80020304": "MV_CODEREADER_E_USB_BANDWIDTH 带宽不足",
    "0x80020305": "MV_CODEREADER_E_USB_DRIVER 驱动不匹配或者未装驱动",
    "0x800203FF": "MV_CODEREADER_E_USB_UNKNOW USB未知的错误",
    "0x80020400": "MV_CODEREADER_E_UPG_FILE_MISMATCH 升级固件不匹配",
    "0x80020401": "MV_CODEREADER_E_UPG_LANGUSGE_MISMATCH 升级固件语言不匹配",
    "0x80020402": "MV_CODEREADER_E_UPG_CONFLICT 升级冲突",
    "0x80020403": "MV_CODEREADER_E_UPG_INNER_ERR 升级时读码器内部出现错误",
    "0x80020404": "MV_CODEREADER_E_UPG_REGRESH_TYPE_ERR 获取读码器型号失败",
    "0x80020405": "MV_CODEREADER_E_UPG_COPY_FPGABIN_ERR 复制FPGA文件失败",
    "0x80020406": "MV_CODEREADER_E_UPG_ZIPEXTRACT_ERR ZIP文件解压失败",
    "0x80020407": "MV_CODEREADER_E_UPG_DAVEXTRACT_ERR DAV文件解压失败",
    "0x80020408": "MV_CODEREADER_E_UPG_DAVCOMPRESS_ERR DAV文件压缩失败",
    "0x80020409": "MV_CODEREADER_E_UPG_ZIPCOMPRESS_ERR ZIP文件压缩失败",
    "0x80020410": "MV_CODEREADER_E_UPG_GET_PROGRESS_TIMEOUT_ERR 获取升级进度超时",
    "0x80020411": "MV_CODEREADER_E_UPG_SEND_QUERY_PROGRESS_ERR 发送进度查询指令失败",
    "0x80020412": "MV_CODEREADER_E_UPG_RECV_QUERY_PROGRESS_ERR 接收进度查询指令失败",
    "0x80020413": "MV_CODEREADER_E_UPG_GET_QUERY_PROGRESS_ERR 获取查询进度失败",
    "0x80020414": "MV_CODEREADER_E_UPG_GET_MAX_QUERY_PROGRESS_ERR 获得最大进度失败",
    "0x80020465": "MV_CODEREADER_E_UPG_CHECKT_PACKET_FAILED 文件验证失败",
    "0x80020466": "MV_CODEREADER_E_UPG_FPGA_PROGRAM_FAILED FPGA程序升级失败",
    "0x80020467": "MV_CODEREADER_E_UPG_WATCHDOG_FAILED 看门狗升级失败",
    "0x80020468": "MV_CODEREADER_E_UPG_CAMERA_AND_BARE_FAILED 裸相机升级失败",
    "0x80020469": "MV_CODEREADER_E_UPG_RETAIN_CONFIG_FAILED 保留配置文件失败",
    "0x8002046A": "MV_CODEREADER_E_UPG_FPGA_DRIVER_FAILED FPGA驱动升级失败",
    "0x8002046B": "MV_CODEREADER_E_UPG_SPI_DRIVER_FAILED SPI驱动升级失败",
    "0x8002046C": "MV_CODEREADER_E_UPG_REBOOT_SYSTEM_FAILED 重新启动失败",
    "0x8002046D": "MV_CODEREADER_E_UPG_UPSELF_FAILED 升级服务升级失败",
    "0x8002046E": "MV_CODEREADER_E_UPG_STOP_RELATION_PROGRAM_FAILED 停止相关服务失败",
    "0x8002046F": "MV_CODEREADER_E_UPG_DEVCIE_TYPE_INCONSISTENT 设备类型不一致",
    "0x80020470": "MV_CODEREADER_E_UPG_READ_ENCRYPT_INFO_FAILED 读取加密信息失败",
    "0x80020471": "MV_CODEREADER_E_UPG_PLAT_TYPE_INCONSISTENT 设备平台错误",
    "0x80020472": "MV_CODEREADER_E_UPG_CAMERA_TYPE_INCONSISTENT 读码器型号错误",
    "0x80020473": "MV_CODEREADER_E_UPG_DEVICE_UPGRADING 读码器正在升级",
    "0x80020474": "MV_CODEREADER_E_UPG_UNZIP_FAILED 升级包解压失败",
    "0x80020475": "MV_CODEREADER_E_UPG_BLE_DISCONNECT 巴枪蓝牙未连接",
    "0x80020476": "MV_CODEREADER_E_UPG_BATTERY_NOTENOUGH 电量不足",
    "0x80020477": "MV_CODEREADER_E_UPG_RTC_NOT_PRESENT 巴枪未放在底座上",
    "0x80020478": "MV_CODEREADER_E_UPG_APP_ERR APP升级失败",
    "0x80020479": "MV_CODEREADER_E_UPG_L3_ERR L3升级失败",
    "0x8002047A": "MV_CODEREADER_E_UPG_MCU_ERR MCU升级失败",
    "0x8002047B": "MV_CODEREADER_E_UPG_PLATFORM_DISMATCH 平台不匹配",
    "0x8002047C": "MV_CODEREADER_E_UPG_TYPE_DISMATCH 型号不匹配",
    "0x8002047D": "MV_CODEREADER_E_UPG_SPACE_DISMATCH 空间不匹配",
    "0x8002047E": "MV_CODEREADER_E_UPG_MEM_DISMATCH 内存不匹配",
    "0x8002047F": "MV_CODEREADER_E_UPG_NET_TRANS_ERROR 网络传输异常，请重新升级",
    "0x800204FF": "MV_CODEREADER_E_UPG_UNKNOW 升级时未知错误",
    "0x80020500": "MV_CODEREADER_E_CREAT_SOCKET 创建Socket错误",
    "0x80020501": "MV_CODEREADER_E_BIND_SOCKET 绑定错误",
    "0x80020502": "MV_CODEREADER_E_CONNECT_SOCKET 连接错误",
    "0x80020503": "MV_CODEREADER_E_GET_HOSTNAME 获取主机名错误",
    "0x80020504": "MV_CODEREADER_E_NET_WRITE 写入数据错误",
    "0x80020505": "MV_CODEREADER_E_NET_READ 读取数据错误",
    "0x80020506": "MV_CODEREADER_E_NET_SELECT Select错误",
    "0x80020507": "MV_CODEREADER_E_NET_TIMEOUT 超时",
    "0x80020508": "MV_CODEREADER_E_NET_ACCEPT 接收错误",
    "0x800205FF": "MV_CODEREADER_E_NET_UNKNOW 网络未知错误"
}

class MvCodeReaderGvspPixelType(Enum):
    PixelType_CodeReader_Gvsp_Undefined = -1,
    PixelType_CodeReader_Gvsp_Mono1p = 16842807,
    PixelType_CodeReader_Gvsp_Mono2p = 16908344,
    PixelType_CodeReader_Gvsp_Mono4p = 17039417,
    PixelType_CodeReader_Gvsp_Mono8 = 17301505,
    PixelType_CodeReader_Gvsp_Mono8_Signed = 17301506,
    PixelType_CodeReader_Gvsp_Mono10 = 17825795,
    PixelType_CodeReader_Gvsp_Mono10_Packed = 17563652,
    PixelType_CodeReader_Gvsp_Mono12 = 17825797,
    PixelType_CodeReader_Gvsp_Mono12_Packed = 17563654,
    PixelType_CodeReader_Gvsp_Mono14 = 17825829,
    PixelType_CodeReader_Gvsp_Mono16 = 17825799,
    PixelType_CodeReader_Gvsp_BayerGR8 = 17301512,
    PixelType_CodeReader_Gvsp_BayerRG8 = 17301513,
    PixelType_CodeReader_Gvsp_BayerGB8 = 17301514,
    PixelType_CodeReader_Gvsp_BayerBG8 = 17301515,
    PixelType_CodeReader_Gvsp_BayerGR10 = 17825804,
    PixelType_CodeReader_Gvsp_BayerRG10 = 17825805,
    PixelType_CodeReader_Gvsp_BayerGB10 = 17825806,
    PixelType_CodeReader_Gvsp_BayerBG10 = 17825807,
    PixelType_CodeReader_Gvsp_BayerGR12 = 17825808,
    PixelType_CodeReader_Gvsp_BayerRG12 = 17825809,
    PixelType_CodeReader_Gvsp_BayerGB12 = 17825810,
    PixelType_CodeReader_Gvsp_BayerBG12 = 17825811,
    PixelType_CodeReader_Gvsp_BayerGR10_Packed = 17563686,
    PixelType_CodeReader_Gvsp_BayerRG10_Packed = 17563687,
    PixelType_CodeReader_Gvsp_BayerGB10_Packed = 17563688,
    PixelType_CodeReader_Gvsp_BayerBG10_Packed = 17563689,
    PixelType_CodeReader_Gvsp_BayerGR12_Packed = 17563690,
    PixelType_CodeReader_Gvsp_BayerRG12_Packed = 17563691,
    PixelType_CodeReader_Gvsp_BayerGB12_Packed = 17563692,
    PixelType_CodeReader_Gvsp_BayerBG12_Packed = 17563693,
    PixelType_CodeReader_Gvsp_BayerGR16 = 17825838,
    PixelType_CodeReader_Gvsp_BayerRG16 = 17825839,
    PixelType_CodeReader_Gvsp_BayerGB16 = 17825840,
    PixelType_CodeReader_Gvsp_BayerBG16 = 17825841,
    PixelType_CodeReader_Gvsp_RGB8_Packed = 35127316,
    PixelType_CodeReader_Gvsp_BGR8_Packed = 35127317,
    PixelType_CodeReader_Gvsp_RGBA8_Packed = 35651606,
    PixelType_CodeReader_Gvsp_BGRA8_Packed = 35651607,
    PixelType_CodeReader_Gvsp_RGB10_Packed = 36700184,
    PixelType_CodeReader_Gvsp_BGR10_Packed = 36700185,
    PixelType_CodeReader_Gvsp_RGB12_Packed = 36700186,
    PixelType_CodeReader_Gvsp_BGR12_Packed = 36700187,
    PixelType_CodeReader_Gvsp_RGB16_Packed = 36700211,
    PixelType_CodeReader_Gvsp_RGB10V1_Packed = 35651612,
    PixelType_CodeReader_Gvsp_RGB10V2_Packed = 35651613,
    PixelType_CodeReader_Gvsp_RGB12V1_Packed = 35913780,
    PixelType_CodeReader_Gvsp_RGB565_Packed = 34603061,
    PixelType_CodeReader_Gvsp_BGR565_Packed = 34603062,
    PixelType_CodeReader_Gvsp_YUV411_Packed = 34340894,
    PixelType_CodeReader_Gvsp_YUV422_Packed = 34603039,
    PixelType_CodeReader_Gvsp_YUV422_YUYV_Packed = 34603058,
    PixelType_CodeReader_Gvsp_YUV444_Packed = 35127328,
    PixelType_CodeReader_Gvsp_YCBCR8_CBYCR = 35127354,
    PixelType_CodeReader_Gvsp_YCBCR422_8 = 34603067,
    PixelType_CodeReader_Gvsp_YCBCR422_8_CBYCRY = 34603075,
    PixelType_CodeReader_Gvsp_YCBCR411_8_CBYYCRYY = 34340924,
    PixelType_CodeReader_Gvsp_YCBCR601_8_CBYCR = 35127357,
    PixelType_CodeReader_Gvsp_YCBCR601_422_8 = 34603070,
    PixelType_CodeReader_Gvsp_YCBCR601_422_8_CBYCRY = 34603076,
    PixelType_CodeReader_Gvsp_YCBCR601_411_8_CBYYCRYY = 34340927,
    PixelType_CodeReader_Gvsp_YCBCR709_8_CBYCR = 35127360,
    PixelType_CodeReader_Gvsp_YCBCR709_422_8 = 34603073,
    PixelType_CodeReader_Gvsp_YCBCR709_422_8_CBYCRY = 34603077,
    PixelType_CodeReader_Gvsp_YCBCR709_411_8_CBYYCRYY = 34340930,
    PixelType_CodeReader_Gvsp_RGB8_Planar = 35127329,
    PixelType_CodeReader_Gvsp_RGB10_Planar = 36700194,
    PixelType_CodeReader_Gvsp_RGB12_Planar = 36700195,
    PixelType_CodeReader_Gvsp_RGB16_Planar = 36700196,
    PixelType_CodeReader_Gvsp_Jpeg = -2145910783,
    PixelType_CodeReader_Gvsp_Coord3D_ABC32f = 39846080,
    PixelType_CodeReader_Gvsp_Coord3D_ABC32f_Planar = 39846081,
    PixelType_CodeReader_Gvsp_Coord3D_AC32f = 37748930,
    PixelType_CodeReader_Gvsp_COORD3D_DEPTH_PLUS_MASK = -2112094207


class MV_CODEREADER_IAMGE_TYPE(Enum):
   MV_CODEREADER_Image_Undefined = 0,
   MV_CODEREADER_Image_Mono8 = 1,
   MV_CODEREADER_Image_Jpeg = 2,
   MV_CODEREADER_Image_Bmp = 3,
   MV_CODEREADER_Image_RGB24 = 4,
   MV_CODEREADER_Image_Png = 5,
   MV_CODEREADER_Image_Tif = 6

@dataclass
class MvFrameTimeoutInfoList:
        nWidth: c_uint16
        nHeight: c_uint16
        enPixelType: MvCodeReaderGvspPixelType
        nTriggerIndex: c_uint
        nFrameNum: c_uint
        nFrameLen: c_uint
        nDevTimeStampHigh: c_uint32
        nDevTimeStampLow: c_uint32
        nResultType: c_uint
        chResult: c_char
        bIsGetCode: c_bool
        pImageWaybill: c_char
        nImageWaybillLen: c_uint
        enWaybillImageType: MV_CODEREADER_IAMGE_TYPE
        bFlaseTrigger: c_uint
        nFocusScore: c_uint
        nChannelID: c_uint
        nImageCost: c_uint
        nRes: c_short
        nWholeFlag: c_short
        nReserved: c_uint * 41

class MvFrameTimeoutInfoList(Structure):
    _fields_ = [
        ("nWidth", c_uint16),
        ("nHeight", c_uint16),
        ("enPixelType", c_uint),
        ("nTriggerIndex", c_uint),
        ("nFrameNum", c_uint),
        ("nFrameLen", c_uint),
        ("nDevTimeStampHigh", c_uint32),
        ("nDevTimeStampLow", c_uint32),
        ("nResultType", c_uint),
        ("chResult", c_char),
        ("bIsGetCode", c_bool),
        ("pImageWaybill", c_char),
        ("nImageWaybillLen", c_uint),
        ("enWaybillImageType",c_uint),
        ("bFlaseTrigger", c_uint),
        ("nFocusScore", c_uint),
        ("nChannelID", c_uint),
        ("nImageCost", c_uint),
        ("nRes", c_short),
        ("nWholeFlag", c_short),
        ("nReserved", c_uint * 41)
    ]

class MvDeviceInfoList(Structure):
    _fields_ = [
        ("nDeviceNum", c_uint32),
        ("pDeviceInfo", c_void_p * 256)
    ]



MV_CODEREADER_MAX_BCR_CODE_LEN = 256
class MV_CODEREADER_POINT_I(Structure):
    _fields_ = [
        ("x", c_int),  # x坐标
        ("y", c_int)   # y坐标
    ]
class MV_CODEREADER_BCR_INFO(Structure):
    _fields_ = [
        ("nID", c_uint),  # 条码ID
        ("chCode", c_char * MV_CODEREADER_MAX_BCR_CODE_LEN ),  # 条码字符
        ("nLen", c_uint),  # 字符长度
        ("nBarType", c_uint),  # 条码类型
        ("pt", MV_CODEREADER_POINT_I * 4),  # 条码位置 (假设有4个点)
        ("nAngle", c_int),  # 条码角度 (10倍)
        ("nMainPackageId", c_uint),  # 主包ID
        ("nSubPackageId", c_uint),  # 次包ID
        ("sAppearCount", c_ushort),  # 条码识别次数
        ("sPPM", c_ushort),  # PPM (10倍)
        ("sAlgoCost", c_ushort),  # 算法耗时
        ("sSharpness", c_ushort)  # 图像清晰度 (10倍)
    ]

MAX_CODEREADER_BCR_COUNT = 200
class MV_CODEREADER_RESULT_BCR(Structure):
    _fields_ = [
        ("nCodeNum", c_uint),  # 条码数量
        ("stBcrInfo", MV_CODEREADER_BCR_INFO * MAX_CODEREADER_BCR_COUNT),  # 条码信息
        ("nNoReadNum", c_ushort),  # 有码无读数量
        ("nRes", c_ushort),  # 保留字节
        ("nReserved", c_uint * 3)  # 保留字节
    ]


class MV_CODEREADER_WAYBILL_INFO(Structure):
    _fields_ = [
        ("fCenterX", c_float),  # 中心点列坐标
        ("fCenterY", c_float),  # 中心点行坐标
        ("fWidth", c_float),  # 矩形宽度
        ("fHeight", c_float),  # 矩形高度
        ("fAngle", c_float),  # 矩形角度
        ("fConfidence", c_float),  # 置信度

        # 面单图片
        ("pImageWaybill", POINTER(c_ubyte)),  # 指向无符号字符（字节）的指针
        ("nImageLen", c_uint),  # 图像长度

        ("nOcrRowNum", c_uint),  # 当前面单内的OCR行数
        ("nReserved", c_uint * 11)  # 保留字节
    ]

class MV_CODEREADER_WAYBILL_LIST(Structure):
    _fields_ = [
        ("nWaybillNum", c_uint),  # 面单数量
        ("enWaybillImageType", c_uint),  # 面单图像类型 (假设用unsigned int表示)
        ("stWaybillInfo", MV_CODEREADER_WAYBILL_INFO * 50),  # 面单信息数组
        ("nOcrAllNum", c_uint),  # 所有面单内的OCR总行数
        ("nReserved", c_uint * 3)  # 保留字节
    ]
class MV_CODEREADER_OCR_ROW_INFO(Structure):
    _fields_ = [
        ("nID", c_uint),                              # OCR ID
        ("nOcrLen", c_uint),                          # OCR字符实际真实长度
        ("chOcr", c_char * 128),  # 识别到的OCR字符
        ("fCharConfidence", c_float),                 # 字符行整体置信度
        ("nOcrRowCenterX", c_uint),                   # 单行OCR中心点列坐标
        ("nOcrRowCenterY", c_uint),                   # 单行OCR中心点行坐标
        ("nOcrRowWidth", c_uint),                     # 单行OCR矩形宽度，宽度为长半轴
        ("nOcrRowHeight", c_uint),                    # 单行OCR矩形高度，高度为短半轴
        ("fOcrRowAngle", c_float),                    # 单行OCR矩形角度
        ("fDeteConfidence", c_float),                 # 单行OCR定位置信度
        ("sOcrAlgoCost", c_ushort),                   # OCR算法耗时 单位ms
        ("sReserved", c_ushort),                      # 预留
        ("nReserved", c_int * 31),                    # 预留
    ]
class MV_CODEREADER_OCR_INFO_LIST(Structure):
    _fields_ = [
        ("nOCRAllNum", c_uint),                       # 所有面单内的OCR总行数
        ("stOcrRowInfo", MV_CODEREADER_OCR_ROW_INFO * 100),  # OCR行基础信息
        ("nReserved", c_int * 8),                     # 保留字节
    ]
class UnparsedOcrList(Union):
    _fields_ = [
        ("pstOcrList", POINTER(MV_CODEREADER_OCR_INFO_LIST)),  # OCR信息
        ("nAligning", c_int64)  # 对齐数
    ]

class MV_CODEREADER_IMAGE_OUT_INFO_EX(Structure):
    _fields_ = [
        ("nWidth", c_ushort),
        ("nHeight", c_ushort),
        ("enPixelType", c_uint),
        ("nTriggerIndex", c_uint),
        ("nFrameNum", c_uint),
        ("nFrameLen", c_uint),
        ("nTimeStampHigh", c_uint),
        ("nTimeStampLow", c_uint),
        ("bFlaseTrigger", c_uint),
        ("nFocusScore", c_uint),
        ("bIsGetCode", c_bool), # 是否获取到条形码
        ("pstCodeList", POINTER(MV_CODEREADER_RESULT_BCR)),# 条码信息列表
        ("pstWaybillList", POINTER(MV_CODEREADER_WAYBILL_LIST)),  # 面单信息指针
        ("nEventID", c_uint),  # 事件ID
        ("nChannelID", c_uint),  # 对应Stream通道序号
        ("nImageCost", c_uint),  # 帧图像在相机内部的处理耗时
        ("UnparsedOcrList", UnparsedOcrList),  # 联合体
        ("nWholeFlag", c_ushort),  # 整图标记
        ("nRes", c_ushort),  # 保留字节
        ("nReserved", c_uint * 3)  # 保留字节数组
    ]

def get_error_info(fn):
    """
    装饰器,解析错误码的装饰器
    :param fn: 调用的相机驱动API
    :return:
    """

    def get_info_str(*args):
        ret = fn(*args)
        try:
            errStr = '0x' + (str('%x' % ret)).upper()
            res = errorDict.get(errStr, "相机的错误字典中,没有收录对应的错误信息")
            if "OK" in res:
                res = 0
            return res
        except Exception as e:
            errorInfo = "in get_error_info() error : {}".format(str(e))
            print(errorInfo)
            return errorInfo

    return get_info_str
class CodeCamera(object):
    def __init__(self, cameraId):
        self.id = cameraId
        self.logger = HdLogger()
        try:
            self.api = cdll.LoadLibrary(CODE_LIB_PATH)
        except Exception as e:
            self.api = None
            errorInfo = "扫码相机驱动加载失败,error : {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)
        self.nRet = "MV_CODEREADER_OK 成功，无错误"
        self.deviceList = MvDeviceInfoList()
        self.bufferSize = (1280*1024) * sizeof(c_char)
        self.keepRawBuffer = create_string_buffer(self.bufferSize)
        self.handler = c_uint64(0)  # 相机句柄
        self.frameTimeoutInfo = MvFrameTimeoutInfoList()
        self.imageCodeInfo = MV_CODEREADER_IMAGE_OUT_INFO_EX()
        # self.enum_devices()
        # self.create_handler()

    @get_error_info
    def enum_devices(self):
        """
        枚举子网传输协议对应的所有的设备.
        :return:
        """
        tLayerType = 1 # Gige设备
        self.api.MV_CODEREADER_EnumDevices.restype = c_uint
        self.api.MV_CODEREADER_EnumDevices.argtype = (c_uint, pointer(self.deviceList))
        return self.api.MV_CODEREADER_EnumCodeReader(byref(self.deviceList))

    @get_error_info
    def create_handler(self):
        """
        创建设备操作句柄,根据id号
        :return:
        """
        self.api.MV_CODEREADER_CreateHandle.argtype = (c_void_p, c_void_p)
        self.api.MV_CODEREADER_CreateHandle.restype = c_uint
        return self.api.MV_CODEREADER_CreateHandle(byref(self.handler), c_void_p(self.deviceList.pDeviceInfo[self.id]))

    @get_error_info
    def close_device(self):
        """
        通过MV_CODEREADER_OpenDevice连接设备之后,可以公国该节后断开设备连接,释放资源
        :return: 成功返回MV_OK,失败返回错误码
        """
        self.api.MV_CODEREADER_CloseDevice.argtype = c_uint64
        self.api.MV_CODEREADER_CloseDevice.restype = c_uint
        return self.api.MV_CODEREADER_CloseDevice(self.handler)

    @get_error_info
    def destroy_handler(self):
        """
        销毁设备的实例,以及相应的资源
        :return: 成功返回MV_OK(0),失败返回错误码
        """
        self.api.MV_CODEREADER_DestroyHandle.argtype = c_uint64
        self.api.MV_CODEREADER_DestroyHandle.restype = c_uint
        return self.api.MV_CODEREADER_DestroyHandle(self.handler)

    @get_error_info
    def open_device(self):
        """
        打开设备,连接设备.1表示打开的设备的模式是独占模式,一般就是用此模式
        :return:
        """
        self.api.MV_CODEREADER_OpenDevice.argtype = c_uint64
        self.api.MV_CODEREADER_OpenDevice.restype = c_uint
        return self.api.MV_CODEREADER_OpenDevice(self.handler)

    @get_error_info
    def clear_buffer(self):
        """
        清空设备的缓存
        :return:
        """
        self.api.MV_CODEREADER_ClearImageBuffer.argtype = c_uint64
        self.api.MV_CODEREADER_ClearImageBuffer.restype = c_uint
        return self.api.MV_CODEREADER_ClearImageBuffer(self.handler)

    @get_error_info
    def start_grabbing(self):
        """
        相机开抓图打开
        :return:
        """
        self.api.MV_CODEREADER_StartGrabbing.argtype = c_uint64
        self.api.MV_CODEREADER_StartGrabbing.restype = c_uint
        return self.api.MV_CODEREADER_StartGrabbing(self.handler)

    @get_error_info
    def stop_grabbing(self):
        """
        相机抓图关闭
        :return:
        """
        self.api.MV_CODEREADER_StopGrabbing.argtype = c_uint64
        self.api.MV_CODEREADER_StopGrabbing.restype = c_uint
        return self.api.MV_CODEREADER_StopGrabbing(self.handler)

    def is_device_online(self):
        """
        设备是否是在线连接状态
        :return:处于连接状态返回True,否则返回False
        """
        self.api.MV_CODEREADER_IsDeviceAccessible.argtype = c_uint64
        self.api.MV_CODEREADER_IsDeviceAccessible.restype = c_bool
        return self.api.MV_CODEREADER_IsDeviceAccessible(self.handler)

    @get_error_info
    def get_one_frame_with_timeout(self, timeOut):
        """
        获取一帧的图片,使用超时机制,超时时间限定是3秒.
        :return:
        """
        self.api.MV_CODEREADER_GetOneFrameTimeout.argtype = (c_uint64, c_char_p, POINTER(MvFrameTimeoutInfoList), c_int)
        self.api.MV_CODEREADER_GetOneFrameTimeout.restype = c_uint
        return self.api.MV_CODEREADER_GetOneFrameTimeout(self.handler, byref(self.keepRawBuffer),
                                                 byref(self.frameTimeoutInfo), c_int(timeOut))

    def get_image(self):
        """
        获取图像
        :return:
        """
        timeOut = 3000  # 超时时间,单位毫秒
        ret = self.get_one_frame_with_timeout(timeOut)
        if ret != 0:
            print("in LineCamera.get_image() error : {}".format(ret))
            return -1, ret

        image = self.get_image_buffer()[1]
        return 0, image

    def get_image_buffer(self):
        """
        获取图片的保存的buffer,转换成一张图片.
        :return:
        """
        try:
            buffer = np.frombuffer(self.keepRawBuffer, c_uint8)[0:1024 * 1280]
            buffer = buffer.reshape(1280, 1024)
        except Exception as e:
            errorInfo = "in get_image_buffer() error : {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)
            return str(e), None
        return 0, buffer

    def safe_close(self):
        """
        安全关闭相机,断开相机的连接,最后要消除句柄的连接.
        :return:
        """
        try:
            self.stop_grabbing()
            self.close_device()
        except Exception as e:
            errorInfo = "in LineCamera.safe_close() error: {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)
        finally:
            self.destroy_handler()

    def re_connect_code_camera(self):
        """
        重新连接设备
        :return:
        """
        try:
            self.safe_close()
            gevent.sleep(0.1)
        except Exception as e:
            errorInfo = "in LineCamera.re_connect_line_camera,error: {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)
        self.enum_devices()
        self.create_handler()
        return self.open_device()


    @get_error_info
    def get_image_and_code(self):
        timeOut = 3000
        self.api.MV_CODEREADER_GetOneFrameTimeoutEx2.argtype = (c_uint64, c_char_p,
                                                                POINTER(MV_CODEREADER_IMAGE_OUT_INFO_EX), c_int)
        self.api.MV_CODEREADER_GetOneFrameTimeoutEx2.restype = c_uint
        ret = self.api.MV_CODEREADER_GetOneFrameTimeoutEx2(
            self.handler,byref(self.keepRawBuffer),byref(self.imageCodeInfo),c_int(timeOut))
        calcCodeList = [] # 最终识别的字符列表
        if ret != 0:
            print("条形码读取失败")
        else:
            getCodeOk = self.imageCodeInfo.bIsGetCode # 是否获取到条形码
            print("条码是否获取OK")
            codeList = self.imageCodeInfo.pstCodeList.stBcrInfo
            for code in   codeList:
                print(f"识别到条码类型: {code.nBarType},条码字符: {code.chCode},长度: {code.nLen}")
                if code.nLen != 0:
                    calcCodeList.append(code.chCode)
        return ret,calcCodeList




if __name__ == '__main__':
    cc = CodeCamera(0)
    cc.enum_devices()
    cc.create_handler()
    ret = cc.open_device()
    print(ret)
    ret = cc.start_grabbing()
    print(ret)
    ret,wordList = cc.get_image_and_code()
    print(ret,wordList)
    ret = cc.stop_grabbing()
    ret = cc.close_device()
    ret = cc.destroy_handler()